package com.yanqu.road.server.channelserver.manager.activity.entername;

import com.yanqu.road.dao.impl.channelcenter.ChannelActivityDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.entername.ActivityGroupMatch;
import com.yanqu.road.entity.activity.entername.EnterNameParam;
import com.yanqu.road.entity.activity.entername.UserEnterName;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.logic.activity.entername.ChannelEnterNameHelper;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.pb.cross3.activity.EnterNameProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.channelserver.logic.ChannelMessageHelper;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRankModel;
import com.yanqu.road.server.channelserver.manager.activity.pasture.ChannelPastureMgr;
import com.yanqu.road.server.protocol.Cross3Protocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelEnterNameMgr extends TempMgr {

    private static Map<Integer, ActivityInfo> activityInfoMap = new ConcurrentHashMap<>();

    private static final Map<Integer, Object> lockMap = new ConcurrentHashMap<>();

    //activityId
    private static Map<Integer, EnterNameModel> enterNameModelMap = new ConcurrentHashMap<>();

    //activityId
    private static Map<Integer, EnterNameActivity> nameActivityMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        for (ActivityInfo activityInfo : activityInfoMap.values()) {
            //活动有效期
            if(System.currentTimeMillis() / 1000 > activityInfo.getEndShowTime()){
                continue;
            }

            //加载分组数据
            EnterNameModel model = new EnterNameModel(activityInfo, null, null, new EnterNameGroupCtrl());
            if(model.init(true)){
                enterNameModelMap.put(activityInfo.getActivityId(), model);
            }
        }
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {
        for (Map.Entry<Integer, EnterNameModel> entry : enterNameModelMap.entrySet()) {
            try{
                entry.getValue().save();
            }catch (Exception e){
                getLogger().error("save activity{} error {}", entry.getKey(), e.getMessage());
            }
        }
        return true;
    }

    /**
     * 报名
     */
    public static int enterNameAdd(EnterNameParam param){
        Object obj = getActivityLock(param.getActivityId());
        UserEnterName userEnterName;
        int ret;
        synchronized (obj){
            EnterNameModel enterNameModel = enterNameModelMap.get(param.getActivityId());
            if(enterNameModel == null){
                ActivityInfo activityInfo = getActivityInfoMap().get(param.getActivityId());
                if(activityInfo == null){
                    activityInfo = new ChannelActivityDaoImpl().getActivityInfoById(param.getActivityId(), ChannelConfig.CHANNEL_ACTIVITY_TIME_ZONE);
                    if(activityInfo == null){
                        return GameErrorCode.E_ACTIVITY_NO_FOUND;
                    }
                    addActivityInfo(activityInfo);
                }

                //初始 model
                enterNameModel = new EnterNameModel(activityInfo, null, null, new EnterNameGroupCtrl());
                if(enterNameModel.init(true)){
                    enterNameModelMap.put(activityInfo.getActivityId(), enterNameModel);
                }
            }
            userEnterName = enterNameModel.getUserEnterName(param.getUserId());
            if(userEnterName == null) {
                userEnterName = initUserEnterName(param);
            }
            ret = enterNameModel.addEnterName(userEnterName);
            if(ret == 0){
                //enterNameModel.initCountListMsg();
            }
        }

        //报名成功
        if(ret == 0){

            EnterNameActivity enterNameActivity = getEnterNameActivity(param.getActivityId());
            if(enterNameActivity != null) {
                //单地区top榜单
                EnterNameRank rank = getEnterNameRank(param);
                rank.setConditionType(enterNameActivity.getUserConditionType());
                ChannelEnterNameRankMgr.changeZoneTop50UserRank(param.getActivityId(), enterNameActivity.getUserConditionType(),
                        param.getZoneId(), rank);
            }

            //to cross3 cache  聊天等，玩家登录验证
            EnterNameProto.EnterNameAddRespMsg.Builder respMsg = EnterNameProto.EnterNameAddRespMsg.newBuilder();
            respMsg.setRet(ret);
            EnterNameProto.UserEnterNameMsg.Builder nameMsg = ChannelEnterNameHelper.buildUserEnterNameMsg(userEnterName);
            respMsg.setEnterName(nameMsg);
            ChannelMessageHelper.sendToChannel(YanQuMessageUtils.buildMessage(Cross3Protocol.C3_ENTER_NAME_ADD_FROM_CHANNEL, respMsg), param.getChannelId());

            //to game server   自动报名，客户端
            EnterNameProto.ChannelEnterNameBatchSyncMsg.Builder gameSync = EnterNameProto.ChannelEnterNameBatchSyncMsg.newBuilder();
            gameSync.setActivityId(param.getActivityId());
            gameSync.setServerId(param.getServerId());

            EnterNameProto.ChannelEnterNameMsg.Builder builder = EnterNameProto.ChannelEnterNameMsg.newBuilder();
            builder.setUserId(userEnterName.getUserId());
            builder.setZoneId(userEnterName.getZoneId());
            gameSync.addName(builder);
            ChannelMessageHelper.sendGamePacket(Protocol.S_ENTER_NAME_NAME_SYNC_FROM_CHANNEL, gameSync, param.getChannelId(), param.getServerId(), 0);
        }
        return ret;
    }

    private static EnterNameRank getEnterNameRank(EnterNameParam param) {
        EnterNameRank enterNameRank = ChannelEnterNameRankMgr.getEnterNameRank(param.getUserId(), param.getChannelId(), 0, eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue(),
                System.currentTimeMillis() / 1000, BigInteger.ZERO, "", param.getUserBaseInfo());
        enterNameRank.setZoneId(param.getZoneId());
        return enterNameRank;
    }

    private static EnterNameRank getEnterNameRank(UserEnterName param) {
        return ChannelEnterNameRankMgr.getEnterNameRank(param.getUserId(), param.getChannelId(), param.getGroupId(), eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue(),
                System.currentTimeMillis() / 1000, BigInteger.ZERO, "", param.getUserBaseInfo());
    }

    public static int enterNameBatchAdd(int activityId, int channelId, long serverId, List<EnterNameParam> list){
        Object obj = getActivityLock(activityId);
        List<UserEnterName> result;
        EnterNameModel enterNameModel;
        synchronized (obj){
            enterNameModel = enterNameModelMap.get(activityId);
            if(enterNameModel == null){
                ActivityInfo activityInfo = getActivityInfoMap().get(activityId);
                if(activityInfo == null){
                    activityInfo = new ChannelActivityDaoImpl().getActivityInfoById(activityId, ChannelConfig.CHANNEL_ACTIVITY_TIME_ZONE);
                    if(activityInfo == null){
                        return GameErrorCode.E_ACTIVITY_NO_FOUND;
                    }
                    addActivityInfo(activityInfo);
                }
                //初始 model
                enterNameModel = new EnterNameModel(activityInfo, null, null, new EnterNameGroupCtrl());
                if(enterNameModel.init(true)){
                    enterNameModelMap.put(activityInfo.getActivityId(), enterNameModel);
                }
            }
            result = enterNameModel.addEnterName(list);
            if(result.size() > 0) {
                //enterNameModel.initCountListMsg();
            }
            getLogger().info("activity {} server {} auto name size {}/{}", activityId, serverId, result.size(), list.size());
        }
        enterNameModel.syncName(activityId, channelId, serverId, result);
        //自动报名，没必要有初始值，因为马上要开始比赛了

        EnterNameActivity enterNameActivity = getEnterNameActivity(activityId);
        if(enterNameActivity != null) {
            for (UserEnterName enterName : result) {
                EnterNameRankModel model = ChannelEnterNameRankMgr.getEnterNameRankModel(activityId, enterNameActivity.getUserConditionType(), enterName.getZoneId());
                //top 达到就不需要初始化
                if(model != null && model.getRankList().size() < 50){
                    EnterNameRank rank = getEnterNameRank(enterName);
                    ChannelEnterNameRankMgr.changeZoneTop50UserRank(enterName.getActivityId(), enterNameActivity.getUserConditionType(),
                            enterName.getZoneId(), rank);
                }
            }
        }
        return 0;
    }

    public static UserEnterName initUserEnterName(EnterNameParam param) {
        UserEnterName userEnterName = new UserEnterName();
        userEnterName.setInsertOption();
        userEnterName.setActivityId(param.getActivityId());
        userEnterName.setUserId(param.getUserId());
        userEnterName.setChannelId(param.getChannelId());
        userEnterName.setZoneId(param.getZoneId());
        userEnterName.setServerId(param.getServerId());
        userEnterName.setUserBaseInfo(param.getUserBaseInfo());
        return userEnterName;
    }

    public static Object getActivityLock(int activityId) {
        Object obj = lockMap.get(activityId);
        if(obj == null){
            synchronized (lockMap){
                obj = lockMap.computeIfAbsent(activityId, k -> new Object());
            }
        }
        return obj;
    }

    public static UserEnterName getUserEnterName(int activityId, long userId){
        EnterNameModel model = enterNameModelMap.get(activityId);
        if(model == null){
            return null;
        }
        return model.getUserEnterName(userId);
    }

    public static EnterNameModel getEnterNameModel(int activityId){
        return enterNameModelMap.get(activityId);
    }

    public static ActivityGroupMatch getActivityGroupMatch(int activityId, long userId){
        EnterNameModel model = enterNameModelMap.get(activityId);
        if(model == null){
            return null;
        }
        UserEnterName userEnterName = model.getUserEnterName(userId);
        if(userEnterName == null){
            return null;
        }
        return model.getActivityGroupMatch(userEnterName.getGroupId());
    }

    private static void addActivityInfo(ActivityInfo activityInfo){
        activityInfoMap.put(activityInfo.getActivityId(), activityInfo);
    }

    public static void setActivityInfo(ActivityInfo activityInfo){
        activityInfoMap.put(activityInfo.getActivityId(), activityInfo);
        if(!lockMap.containsKey(activityInfo.getActivityId())){
            lockMap.put(activityInfo.getActivityId(), new Object());
        }
    }

    /**
     * 活动可领奖期间，活动结束5分钟开始领奖
     */
    public static boolean activityInCanRewardPeriod(ActivityInfo activityInfo){
        if(null == activityInfo){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        return nowTime >= activityInfo.getEndTime() + 300 && nowTime < activityInfo.getEndShowTime();
    }

    /**
     * 活动领奖期间，活动结束10分钟内
     */
    public static boolean activityInSaveRankPeriod(ActivityInfo activityInfo){
        if(null == activityInfo){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        return nowTime >= activityInfo.getEndTime() + 320 && nowTime <= activityInfo.getEndTime() + 600;
    }

    /***
     * 其他活动需要扩展
     */
    public static void putEnterNameActivity(int activityId, EnterNameActivity activity){
        nameActivityMap.put(activityId, activity);
    }

    public static Map<Integer, EnterNameModel> getEnterNameModelMap() {
        return enterNameModelMap;
    }

    public static Map<Integer, ActivityInfo> getActivityInfoMap() {
        return activityInfoMap;
    }

    public static EnterNameActivity getEnterNameActivity(int activityId){
        return nameActivityMap.get(activityId);
    }

    public static void checkActivity() {
        for (ActivityInfo activityInfo : activityInfoMap.values()) {
            //活动有效期
            if (System.currentTimeMillis() / 1000 > activityInfo.getEndShowTime()) {
                continue;
            }
            if(nameActivityMap.containsKey(activityInfo.getActivityId())){
                continue;
            }
            if(activityInfo.getType() == eActivityType.CrossPasture.getValue()){
                nameActivityMap.put(activityInfo.getActivityId(), ChannelPastureMgr.getActivity(activityInfo.getActivityId()));
            }
            if(activityInfo.getType() == eActivityType.AreaWashePkActivity.getValue()){

            }
        }
    }

    public static boolean activityInTime(ActivityInfo activityInfo) {
        if (activityInfo == null) {
            return false;
        }
        long now = System.currentTimeMillis() / 1000;
        return now >= activityInfo.getBeginTime() && now <= activityInfo.getEndTime();
    }

    public static Map<Integer, EnterNameActivity> getNameActivityMap() {
        return nameActivityMap;
    }
}
